package cn.cytong.nk0713.utils;

import cn.cytong.nk0713.utils.nutz.Constants;
import cn.cytong.nk0713.utils.nutz.CustomisedNutDao;
import com.google.common.base.Preconditions;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.entity.Record;

import static org.apache.commons.lang3.Validate.isTrue;

/**
 * 计算卡片的扇区数据和密钥
 */
public class CreditUtil {
    public static final int TYPE_OPERATOR = 1;
    public static final int TYPE_BRANCH = 2;
    public static final int TYPE_PROVIDER = 3;
    public static final Long ROLE_OPERATOR = 2l;
    public static final int CREDIT_CLASS_NO_LIMIT = 100;

    //============================== 信用额度分配 ====================================//

    /**
     * 从网点分配信用给操作员
     *
     * @param branch
     * @param operator
     * @param credit
     */
    public static void allocationToOperator(Record branch, Record operator, int credit, CustomisedNutDao nutDao) throws Exception {
        // 扣除网点信用
        if (branch.get("creditBalance") == null) throw new Exception("网点信用余额为空！");

        int rows = nutDao.getBaseDao().update("ServiceBranch",
                Chain.make("creditBalance", branch.getInt("creditBalance") - credit),
                Cnd.where("id", "=", branch.get("id"))
                        .and("creditBalance", "=", branch.get("creditBalance")));
        /*int rows = JPA.em().createQuery("update models.ServiceBranch set creditBalance=:newCreditBalance where id=:id and creditBalance=:creditBalance")
                .setParameter("newCreditBalance", branch.creditBalance - credit)
                .setParameter("id", branch.id)
                .setParameter("creditBalance", branch.creditBalance)
                .executeUpdate();*/

        if (rows == 0) {
            throw new Exception("网点信用数据更新冲突！");
        }

        // 增加操作员信用
        if (operator.get("creditBalance") == null) throw new Exception("操作员信用余额为空！");

        rows = nutDao.getBaseDao().update("Operator",
                Chain.make("creditBalance", operator.getInt("creditBalance") + credit),
                Cnd.where("id", "=", operator.get("id"))
                        .and("creditBalance", "=", operator.get("creditBalance")));
        /*rows = JPA.em().createQuery("update models.Operator set creditBalance=:newCreditBalance where id=:id and creditBalance=:creditBalance")
                .setParameter("newCreditBalance", operator.creditBalance + credit)
                .setParameter("id", operator.id)
                .setParameter("creditBalance", operator.creditBalance)
                .executeUpdate();*/

        if (rows == 0) {
            throw new Exception("操作员信用数据更新冲突！");
        }
    }

    /**
     * 从服务商分配信用给网点
     *
     * @param provider
     * @param branch
     * @param credit
     */
    public static void allocationToBranch(Record provider, Record branch, int credit, CustomisedNutDao nutDao) throws Exception {
        // 扣除服务商信用
        if (provider.get("creditBalance") == null) throw new Exception("服务商信用余额为空！");

        int rows = nutDao.getBaseDao().update("ServiceProvider",
                Chain.make("creditBalance", provider.getInt("creditBalance") - credit),
                Cnd.where("id", "=", provider.get("id"))
                        .and("creditBalance", "=", provider.get("creditBalance")));
        /*int rows = JPA.em().createQuery("update models.ServiceProvider set creditBalance=:newCreditBalance where id=:id and creditBalance=:creditBalance")
                .setParameter("newCreditBalance", provider.creditBalance - credit)
                .setParameter("id", provider.id)
                .setParameter("creditBalance", provider.creditBalance)
                .executeUpdate();*/

        if (rows == 0) {
            throw new Exception("网点信用数据更新冲突！");
        }

        // 增加网点信用
        if (branch.get("creditBalance") == null) throw new Exception("网点信用余额为空！");

        rows = nutDao.getBaseDao().update("ServiceBranch",
                Chain.make("creditBalance", branch.getInt("creditBalance") + credit),
                Cnd.where("id", "=", branch.get("id"))
                        .and("creditBalance", "=", branch.get("creditBalance")));
        /*rows = JPA.em().createQuery("update models.ServiceBranch set creditBalance=:newCreditBalance where id=:id and creditBalance=:creditBalance")
                .setParameter("newCreditBalance", branch.creditBalance + credit)
                .setParameter("id", branch.id)
                .setParameter("creditBalance", branch.creditBalance)
                .executeUpdate();*/

        if (rows == 0) {
            throw new Exception("操作员信用数据更新冲突！");
        }
    }

    //============================== 信用额度充值 ====================================//

    /**
     * 给操作员充值
     *
     * @param operator
     * @param credit
     */
    public static void rechargeOperator(Record operator, int credit, CustomisedNutDao nutDao) throws Exception {
        // 增加信用
        if (operator.get("creditBalance") == null) throw new Exception("操作员信用余额为空！");
        if (operator.get("creditAddTotal") == null) throw new Exception("操作员信用添加累计为空！");

        int rows = nutDao.getBaseDao().update("Operator",
                Chain.make("creditBalance", operator.getInt("creditBalance") + credit)
                        .add("creditAddTotal", operator.getInt("creditAddTotal") + credit),
                Cnd.where("id", "=", operator.get("id"))
                        .and("creditBalance", "=", operator.get("creditBalance"))
                        .and("creditAddTotal", "=", operator.get("creditAddTotal")));
        /*int rows = JPA.em().createQuery("update models.Operator set creditBalance=:newCreditBalance," +
                " creditAddTotal=:newCreditAddTotal where id=:id and creditBalance=:creditBalance and creditAddTotal=:creditAddTotal")
                .setParameter("newCreditBalance", operator.creditBalance + credit)
                .setParameter("newCreditAddTotal", operator.creditAddTotal + credit)
                .setParameter("id", operator.id)
                .setParameter("creditBalance", operator.creditBalance)
                .setParameter("creditAddTotal", operator.creditAddTotal)
                .executeUpdate();*/

        if (rows == 0) {
            throw new Exception("操作员信用数据更新冲突！");
        }
    }

    /**
     * 给网点充值
     *
     * @param branch
     * @param credit
     */
    public static void rechargeBranch(Record branch, int credit, CustomisedNutDao nutDao) throws Exception {
        // 增加信用
        if (branch.get("creditBalance") == null) throw new Exception("网点信用余额为空！");
        if (branch.get("creditAddTotal") == null) throw new Exception("网点信用添加累计为空！");

        int rows = nutDao.getBaseDao().update("ServiceBranch",
                Chain.make("creditBalance", branch.getInt("creditBalance") + credit)
                        .add("creditAddTotal", branch.getInt("creditAddTotal") + credit),
                Cnd.where("id", "=", branch.get("id"))
                        .and("creditBalance", "=", branch.get("creditBalance"))
                        .and("creditAddTotal", "=", branch.get("creditAddTotal")));
        /*int rows = JPA.em().createQuery("update models.ServiceBranch set creditBalance=:newCreditBalance, " +
                "creditAddTotal=:newCreditAddTotal where id=:id and creditBalance=:creditBalance and creditAddTotal=:creditAddTotal")
                .setParameter("newCreditBalance", branch.creditBalance + credit)
                .setParameter("newCreditAddTotal", branch.creditAddTotal + credit)
                .setParameter("id", branch.id)
                .setParameter("creditBalance", branch.creditBalance)
                .setParameter("creditAddTotal", branch.creditAddTotal)
                .executeUpdate();*/

        if (rows == 0) {
            throw new Exception("网点信用数据更新冲突！");
        }
    }

    /**
     * 给服务商充值
     *
     * @param provider
     * @param credit
     */
    public static void rechargeProvider(Record provider, int credit, CustomisedNutDao nutDao) throws Exception {
        // 增加信用
        if (provider.get("creditBalance") == null) throw new Exception("服务商信用余额为空！");
        if (provider.get("creditAddTotal") == null) throw new Exception("服务商信用添加累计为空！");

        int rows = nutDao.getBaseDao().update("ServiceProvider",
                Chain.make("creditBalance", provider.getInt("creditBalance") + credit)
                        .add("creditAddTotal", provider.getInt("creditAddTotal") + credit),
                Cnd.where("id", "=", provider.get("id"))
                        .and("creditBalance", "=", provider.get("creditBalance"))
                        .and("creditAddTotal", "=", provider.get("creditAddTotal")));
        /*int rows = JPA.em().createQuery("update models.ServiceProvider set creditBalance=:newCreditBalance," +
                " creditAddTotal=:newCreditAddTotal where id=:id and creditBalance=:creditBalance and creditAddTotal=:creditAddTotal")
                .setParameter("newCreditBalance", provider.creditBalance + credit)
                .setParameter("newCreditAddTotal", provider.creditAddTotal + credit)
                .setParameter("id", provider.id)
                .setParameter("creditBalance", provider.creditBalance)
                .setParameter("creditAddTotal", provider.creditAddTotal)
                .executeUpdate();*/

        if (rows == 0) {
            throw new Exception("服务商信用数据更新冲突！");
        }
    }


    //============================== 使用信用额度，用于激活 ====================================//

    /**
     * 使用信用度
     *
     * @param operator
     * @return 1-操作员；2-网点；3-服务商
     * @throws Exception
     */
    public static int deductCredit(Record operator, int credit, CustomisedNutDao nutDao) {

        return deductCreditFromOperator(operator, credit, nutDao);
    }

    /**
     * 使用操作员信用
     *
     * @param operator
     * @param credit
     * @throws Exception
     */
    public static int deductCreditFromOperator(Record operator, int credit, CustomisedNutDao nutDao) {
        // 如果服务商为无限制，则直接返回
        Record provider = nutDao.fetchRecord("select * from serviceProvider where id = ?", operator.get("serviceProvider_id"));
        if (provider.get("creditClass") != null && provider.getInt("creditClass") == CREDIT_CLASS_NO_LIMIT) {
            return -1;
        }

        if (operator.get("creditBalance") != null && operator.getInt("creditBalance") >= credit) {
            // 增加信用
            if (operator.get("creditUseTotal") == null) throw new RuntimeException("操作员信用使用累计为空！");

            int rows = nutDao.getBaseDao().update("Operator",
                    Chain.make("creditBalance", operator.getInt("creditBalance") - credit)
                            .add("creditUseTotal", operator.getInt("creditUseTotal") + credit),
                    Cnd.where("id", "=", operator.get("id"))
                            .and("creditBalance", "=", operator.get("creditBalance"))
                            .and("creditUseTotal", "=", operator.get("creditUseTotal")));
            /*JPA.em().createQuery("update models.Operator set creditBalance=:newCreditBalance," +
                    " creditUseTotal=:newCreditUseTotal where id=:id and creditBalance=:creditBalance and creditUseTotal=:creditUseTotal")
                    .setParameter("newCreditBalance", operator.creditBalance - credit)
                    .setParameter("newCreditUseTotal", operator.creditUseTotal + credit)
                    .setParameter("id", operator.id)
                    .setParameter("creditBalance", operator.creditBalance)
                    .setParameter("creditUseTotal", operator.creditUseTotal)
                    .executeUpdate();*/

            if (rows == 0) {
                throw new RuntimeException("操作员信用数据更新冲突！");
            } else {
                return 1;
            }
        } else if ((Boolean) operator.get("flag")) {
            // 使用上级信用
            Record branch = nutDao.fetchRecord("select * from serviceBranch where id = ?", operator.get("serviceBranch_id"));
            return deductCreditFromBranch(branch, credit, nutDao);
        } else {
            throw new RuntimeException("操作员的信用额度不够，也无权使用网点信用额度！");
        }
    }

    /**
     * 使用网点信用
     *
     * @param branch
     * @param credit
     * @throws Exception
     */
    private static int deductCreditFromBranch(Record branch, int credit, CustomisedNutDao nutDao) {
        if (branch.get("creditBalance") != null && branch.getInt("creditBalance") >= credit) {
            // 增加信用
            if (branch.get("creditUseTotal") == null) throw new RuntimeException("网点信用使用累计为空！");

            int rows = nutDao.getBaseDao().update("ServiceBranch",
                    Chain.make("creditBalance", branch.getInt("creditBalance") - credit)
                            .add("creditUseTotal", branch.getInt("creditUseTotal") + credit),
                    Cnd.where("id", "=", branch.get("id"))
                            .and("creditBalance", "=", branch.get("creditBalance"))
                            .and("creditUseTotal", "=", branch.get("creditUseTotal")));
            /*int rows = JPA.em().createQuery("update models.ServiceBranch set creditBalance=:newCreditBalance," +
                    " creditUseTotal=:newCreditUseTotal where id=:id and creditBalance=:creditBalance and creditUseTotal=:creditUseTotal")
                    .setParameter("newCreditBalance", branch.creditBalance - credit)
                    .setParameter("newCreditUseTotal", branch.creditUseTotal + credit)
                    .setParameter("id", branch.id)
                    .setParameter("creditBalance", branch.creditBalance)
                    .setParameter("creditUseTotal", branch.creditUseTotal)
                    .executeUpdate();*/

            if (rows == 0) {
                throw new RuntimeException("网点信用数据更新冲突！");
            } else {
                return 2;
            }
        } else if ((Boolean) branch.get("flag")) {
            // 使用上级信用
            Record provider = nutDao.fetchRecord("select * from serviceProvider where id = ?", branch.get("serviceProvider_id"));
            return deductCreditFromProvider(provider, credit, nutDao);
        } else {
            throw new RuntimeException("网点的信用额度不够，也无权使用服务商信用额度！");
        }
    }

    /**
     * 使用服务商信用
     *
     * @param provider
     * @param credit
     * @throws Exception
     */
    private static int deductCreditFromProvider(Record provider, int credit, CustomisedNutDao nutDao) {
        // 如果服务商为不限定，则不需要扣除信用
        if (provider.get("creditClass") != null && provider.getInt("creditClass") == CREDIT_CLASS_NO_LIMIT) {
            return 3;
        } else if (provider.get("creditBalance") != null && provider.getInt("creditBalance") >= credit) {
            // 增加信用
            if (provider.get("creditUseTotal") == null) throw new RuntimeException("服务商信用使用累计为空！");

            int rows = nutDao.getBaseDao().update("ServiceProvider",
                    Chain.make("creditBalance", provider.getInt("creditBalance") - credit)
                            .add("creditUseTotal", provider.getInt("creditUseTotal") + credit),
                    Cnd.where("id", "=", provider.get("id"))
                            .and("creditBalance", "=", provider.get("creditBalance"))
                            .and("creditUseTotal", "=", provider.get("creditUseTotal")));
            /*int rows = JPA.em().createQuery("update models.ServiceProvider set creditBalance=:newCreditBalance," +
                    " creditUseTotal=:newCreditUseTotal where id=:id and creditBalance=:creditBalance and creditUseTotal=:creditUseTotal")
                    .setParameter("newCreditBalance", provider.creditBalance - credit)
                    .setParameter("newCreditUseTotal", provider.creditUseTotal + credit)
                    .setParameter("id", provider.id)
                    .setParameter("creditBalance", provider.creditBalance)
                    .setParameter("creditUseTotal", provider.creditUseTotal)
                    .executeUpdate();*/

            if (rows == 0) {
                throw new RuntimeException("服务商信用数据更新冲突！");
            } else {
                return 3;
            }
        } else {
            throw new RuntimeException("服务商的信用额度不够！");
        }
    }

    //============================== 恢复信用额度，用于反激活 ====================================//

    /**
     * 恢复信用
     *
     * @param card 卡信息
     */
    public static int recoverCredit(Record card, CustomisedNutDao nutDao) {
        int ret = -1;

        Preconditions.checkNotNull(card, "card不能为空");

        Record log = nutDao.fetchRecord("select * from OperatorServiceLog where card_id = ? and serviceType = ? order by id desc",
                card.get("id"), Constants.service_type_activate_new);
        Preconditions.checkNotNull(log, "未找到卡片的激活记录！");

        // 如果服务商为不限定，则直接返回
        Record operator = nutDao.fetchTableRecord("operator", "id = ?", log.get("operator_id"));
        Record branch = nutDao.fetchTableRecord("ServiceBranch", "id = ?", log.get("branch_id"));
        Record provider = nutDao.fetchTableRecord("ServiceProvider", "id = ?", log.get("provider_id"));
        if (provider.get("creditClass") != null && provider.getInt("creditClass") == CREDIT_CLASS_NO_LIMIT) {
            return ret;
        }

        if (log.get("deductType") != null) {
            int money = getPriceFromCard(card, nutDao).intValue();

            int type = log.getInt("deductType");
            switch (type) {
                case 1: // 操作员信用恢复
                    recoverCredit2Operator(operator, money, nutDao);

                    break;
                case 2: // 网点信用恢复
                    recoverCredit2Branch(branch, money, nutDao);

                    break;
                case 3: // 服务商信用恢复
                    recoverCredit2Provider(provider, money, nutDao);

                    break;

                default:
                    throw new RuntimeException("异常的信用扣除类型！");
            }
            ret = type;
        }

        return ret;
    }

    /**
     * 恢复操作员信用
     *
     * @param operator
     */
    private static void recoverCredit2Operator(Record operator, int credit, CustomisedNutDao nutDao)  {

        // 增加信用
        if (operator.get("creditBalance") == null) throw new RuntimeException("操作员信用余额为空！");
        if (operator.get("creditUseTotal") == null) throw new RuntimeException("操作员信用使用累计为空！");

        int rows = nutDao.getBaseDao().update("Operator",
                Chain.make("creditBalance", operator.getInt("creditBalance") + credit)
                        .add("creditUseTotal", operator.getInt("creditUseTotal") - credit),
                Cnd.where("id", "=", operator.get("id"))
                        .and("creditBalance", "=", operator.get("creditBalance"))
                        .and("creditUseTotal", "=", operator.get("creditUseTotal")));
        /*int rows = JPA.em().createQuery("update models.Operator set creditBalance=:newCreditBalance, " +
                "creditUseTotal=:newCreditUseTotal where id=:id and creditBalance=:creditBalance and creditUseTotal=:creditUseTotal")
                .setParameter("newCreditBalance", operator.creditBalance + credit)
                .setParameter("newCreditUseTotal", operator.creditUseTotal - credit)
                .setParameter("id", operator.id)
                .setParameter("creditBalance", operator.creditBalance)
                .setParameter("creditUseTotal", operator.creditUseTotal)
                .executeUpdate();*/

        if (rows == 0) {
            throw new RuntimeException("操作员信用数据更新冲突！");
        }
    }

    /**
     * 恢复网点信用
     *
     * @param branch
     * @param credit
     * @throws Exception
     */
    private static void recoverCredit2Branch(Record branch, int credit, CustomisedNutDao nutDao) {

        // 增加信用
        if (branch.get("creditBalance") == null) throw new RuntimeException("网点信用余额为空！");
        if (branch.get("creditUseTotal") == null) throw new RuntimeException("网点信用使用累计为空！");

        int rows = nutDao.getBaseDao().update("ServiceBranch",
                Chain.make("creditBalance", branch.getInt("creditBalance") + credit)
                        .add("creditUseTotal", branch.getInt("creditUseTotal") - credit),
                Cnd.where("id", "=", branch.get("id"))
                        .and("creditBalance", "=", branch.get("creditBalance"))
                        .and("creditUseTotal", "=", branch.get("creditUseTotal")));
        /*int rows = JPA.em().createQuery("update models.ServiceBranch set creditBalance=:newCreditBalance," +
                " creditUseTotal=:newCreditUseTotal where id=:id and creditBalance=:creditBalance and creditUseTotal=:creditUseTotal")
                .setParameter("newCreditBalance", branch.creditBalance + credit)
                .setParameter("newCreditUseTotal", branch.creditUseTotal - credit)
                .setParameter("id", branch.id)
                .setParameter("creditBalance", branch.creditBalance)
                .setParameter("creditUseTotal", branch.creditUseTotal)
                .executeUpdate();*/

        if (rows == 0) {
            throw new RuntimeException("网点信用数据更新冲突！");
        }
    }

    /**
     * 恢复服务商信用
     *
     * @param provider
     * @param credit
     * @throws Exception
     */
    private static void recoverCredit2Provider(Record provider, int credit, CustomisedNutDao nutDao) {

        // 增加信用
        if (provider.get("creditBalance") == null) throw new RuntimeException("服务商信用余额为空！");
        if (provider.get("creditUseTotal") == null) throw new RuntimeException("服务商信用使用累计为空！");

        int rows = nutDao.getBaseDao().update("ServiceProvider",
                Chain.make("creditBalance", provider.getInt("creditBalance") + credit)
                        .add("creditUseTotal", provider.getInt("creditUseTotal") - credit),
                Cnd.where("id", "=", provider.get("id"))
                        .and("creditBalance", "=", provider.get("creditBalance"))
                        .and("creditUseTotal", "=", provider.get("creditUseTotal")));
        /*int rows = JPA.em().createQuery("update models.ServiceProvider set creditBalance=:newCreditBalance," +
                " creditUseTotal=:newCreditUseTotal where id=:id and creditBalance=:creditBalance and creditUseTotal=:creditUseTotal")
                .setParameter("newCreditBalance", provider.creditBalance + credit)
                .setParameter("newCreditUseTotal", provider.creditUseTotal - credit)
                .setParameter("id", provider.id)
                .setParameter("creditBalance", provider.creditBalance)
                .setParameter("creditUseTotal", provider.creditUseTotal)
                .executeUpdate();*/

        if (rows == 0) {
            throw new RuntimeException("服务商信用数据更新冲突！");
        }
    }

    public static Double getPriceFromCard(Record card, CustomisedNutDao nutDao) {
        Record product = nutDao.fetchTableRecord("product", "prdtId = ?", card.getInt("productType"));
        isTrue(product != null, "年卡产品信息不存在: cardId(%s), cardNo(%s)", card.getString("cardId"), card.getString("cardNo"));
        return product.getDouble("price");
    }
}
